using System;
using GeoJSON.Net.Geometry;
using GlobalData;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Model.Core.Entity.Dbcontexts;
using Model.Core.Services;
using Newtonsoft.Json.Linq;
using RobotClient.Services;

namespace RobotClient.Controllers
{
    public class RobotFaultHandler : BackgroundService
    {
        private readonly IDbContextFactory<DbcontextBase> contextFactory;
        private readonly IConfiguration configuration;
        private readonly ILogger<RobotFaultHandler> logger;
        private readonly LocalRobotInfo localRobotInfo;
        private readonly PositionMonitorService _positionMonitor;
        private readonly CloudMqClientCtrl _mqClient;
        private readonly MqTopics _mqTopics;
        private readonly JxNavClient _navHelper;

        public RobotFaultHandler(
            IDbContextFactory<DbcontextBase> contextFactory,
            IConfiguration configuration,
            ILogger<RobotFaultHandler> logger,
            LocalRobotInfo localRobotInfo,
            PositionMonitorService positionMonitor,
            CloudMqClientCtrl mqClient,
            MqTopics mqTopics,
            JxNavClient navHelper)
        {
            this.contextFactory = contextFactory;
            this.configuration = configuration;
            this.logger = logger;
            this.localRobotInfo = localRobotInfo;
            _positionMonitor = positionMonitor;
            _mqClient = mqClient;
            _mqTopics = mqTopics;
            _navHelper = navHelper;
        }



        private async Task HandlePositionFault(string faultType, string message)
        {
            var alert = new JObject
            {
                ["robotId"] = this.localRobotInfo.RobotId,
                ["timestamp"] = DateTime.UtcNow.ToString("o"),
                ["faultType"] = faultType,
                ["message"] = message
            };

            // 带重试机制的MQTT消息发送
            const int maxRetries = 3;
            for (int attempt = 1; attempt <= maxRetries; attempt++)
            {
                try
                {
                    logger.LogDebug("尝试第{Attempt}次发送故障告警", attempt);
                    await _mqClient.SendMessageAsync(_mqTopics.FaultAlertTopic, alert.ToString());
                    logger.LogInformation("故障告警发送成功");
                    break;
                }
                catch (Exception ex)
                {
                    logger.LogError(ex, "第{Attempt}次发送故障告警失败", attempt);
                    if (attempt == maxRetries)
                    {
                        logger.LogCritical("所有重试尝试均失败，进入故障安全模式");
                        return;
                    }
                   await Task.Delay(TimeSpan.FromSeconds(1));
                }
            }
        }


        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {

            _navHelper.ActionPointInfo += HandlePositionUpdate;


            while (!stoppingToken.IsCancellationRequested)
            {

                PositionRecord positionRecord = new PositionRecord(lastX, lastY, lastZ);
                _positionMonitor.MaintainPositionQueue(positionRecord);
                bool istrue = await _positionMonitor.CheckPositionReached(positionRecord);
                if(istrue)
                {
                    HandlePositionFault("stagnation", $"机器人已经停滞{_positionMonitor.CalculateStagnationDuration().Minutes}分钟,确认是否需要处理");
                }
                await Task.Delay(10000, stoppingToken); // 每20刷新一次
            }


        }
        double lastX = 0, lastY = 0, lastZ = 0;
        private void HandlePositionUpdate(double arg1, double arg2, double arg3)
        {
            lastX = arg1;
            lastY = arg2;
            lastZ = arg3;
        }
    }
}